package com.ruoyi.system.websocket;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.system.mapper.SysUserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.*;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

@Component
public class SignalingHandler extends TextWebSocketHandler {
    @Autowired
    private SysUserMapper sysUserInfoMapper;
    @Autowired
    private AuthService authService;
    private final ObjectMapper mapper = new ObjectMapper();

    // 存在线会话（id -> session）
    private final Map<String, WebSocketSession> clients = new ConcurrentHashMap<>();
    // sessionId -> clientId（反查）
    private final Map<String, String> sessionToClientId = new ConcurrentHashMap<>();
    // 存储角色（client 或 admin）
    private final Map<String, String> clientRoles = new ConcurrentHashMap<>();
    // 存储管理员会话
    private final Set<WebSocketSession> adminSessions = Collections.synchronizedSet(new HashSet<>());

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        System.out.println("新的WebSocket连接建立: " + session.getId());
    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        System.out.println("Received message from session " + session.getId() + ": " + message.getPayload());

        JsonNode node = mapper.readTree(message.getPayload());
        String type = node.get("type").asText();

        switch (type) {
            case "register":
                handleRegister(session, node);
                break;

            case "offer":
            case "answer":
            case "candidate":
                handleForwardMessage(session, node, message.getPayload());
                break;

            case "start-view":  // 新增直接处理 start-view
                handleStartViewMessage(session, node);
                break;

            case "control":
                handleControlMessage(session, node);
                break;

            case "stop-view":
                handleStopView(session, node);
                break;

            default:
                session.sendMessage(new TextMessage("{\"type\":\"error\",\"message\":\"unknown-type\"}"));
        }
    }
    // 新增专门处理 start-view 的方法
    private void handleStartViewMessage(WebSocketSession session, JsonNode node) throws Exception {
        String target = node.get("target").asText();
        String requester = node.get("requester").asText();

        WebSocketSession targetSession = clients.get(target);
        if (targetSession != null && targetSession.isOpen()) {
            // 直接转发 start-view 消息
            String forwardMessage = String.format(
                    "{\"type\":\"start-view\",\"target\":\"%s\",\"requester\":\"%s\"}",
                    target, requester
            );
            targetSession.sendMessage(new TextMessage(forwardMessage));
            System.out.println("转发开始查看消息到: " + target);
        } else {
            session.sendMessage(new TextMessage(
                    "{\"type\":\"error\",\"message\":\"target-offline\",\"target\":\"" + target + "\"}"
            ));
        }
    }
    private void handleRegister(WebSocketSession session, JsonNode node) throws Exception {
        String clientId = node.get("clientId").asText();
        String role = node.get("role").asText();
        String token = node.get("token").asText();
        String appUser = node.get("appUser").asText();
        String appPassword = node.get("appPassword").asText();
        System.out.println("设备注册: " + clientId + ", 角色: " + role + ", 账号: " + appUser + ", 密码: " + appPassword);
        if (!authService.validateToken(token, clientId, role, appUser, appPassword)) {
            session.sendMessage(new TextMessage("{\"type\":\"register-failed\",\"reason\":\"invalid token\"}"));
            session.close(CloseStatus.NOT_ACCEPTABLE.withReason("invalid token"));
            return;
        }

        clients.put(clientId, session);
        sessionToClientId.put(session.getId(), clientId);
        clientRoles.put(clientId, role);

        // 如果是管理员，添加到管理员集合
        if ("admin".equals(role)) {
            adminSessions.add(session);
            // 立即向该管理员推送当前在线设备列表
            sendOnlineClientsToAdmin(session);
        }

        // 广播在线列表更新给所有管理员
        broadcastOnlineClients();

        session.sendMessage(new TextMessage("{\"type\":\"register-success\",\"clientId\":\"" + clientId + "\",\"role\":\"" + role + "\"}"));
        System.out.println("设备注册成功: " + clientId + ", 角色: " + role);
    }

    private void handleControlMessage(WebSocketSession session, JsonNode node) throws Exception {
        String action = node.get("action").asText();
        String target = node.get("target").asText();

        WebSocketSession targetSession = clients.get(target);
        if (targetSession != null && targetSession.isOpen()) {
            // 转发控制消息给目标设备
            String sourceClientId = sessionToClientId.get(session.getId());
            System.out.println("转发控制消息: " + action + " 从 " + sourceClientId + " 到 " + target);

            targetSession.sendMessage(new TextMessage(node.toString()));
        } else {
            // 目标离线
            session.sendMessage(new TextMessage(
                    "{\"type\":\"error\",\"message\":\"target-offline\",\"target\":\"" + target + "\"}"
            ));
            System.out.println("目标设备离线: " + target);
        }
    }

    private void handleForwardMessage(WebSocketSession session, JsonNode node, String payload) throws Exception {
        String target = node.get("target").asText();
        WebSocketSession targetSession = clients.get(target);

        if (targetSession != null && targetSession.isOpen()) {
            targetSession.sendMessage(new TextMessage(payload));
            System.out.println("消息转发成功: " + node.get("type").asText() + " -> " + target);
        } else {
            // 发送错误消息回原发送者
            session.sendMessage(new TextMessage(
                    "{\"type\":\"error\",\"message\":\"target-offline\",\"target\":\"" + target + "\"}"
            ));
            System.out.println("目标设备离线: " + target);
        }
    }

    private void handleStopView(WebSocketSession session, JsonNode node) throws Exception {
        String targetClientId = node.get("targetClientId").asText(); // 确保字段名一致
        WebSocketSession clientSession = clients.get(targetClientId);

        if (clientSession != null && clientSession.isOpen()) {
            // 向客户端发送停止查看指令
            clientSession.sendMessage(new TextMessage(
                    "{\"type\":\"control\",\"action\":\"stop-view\",\"from\":\"admin\"}"
            ));
            System.out.println("已发送停止查看指令给设备: " + targetClientId);
        }
    }

    // 向单个管理员发送在线设备列表
    private void sendOnlineClientsToAdmin(WebSocketSession adminSession) throws Exception {
        List<Map<String, String>> onlineClients = getOnlineClients();

        Map<String, Object> messageMap = new HashMap<>();
        messageMap.put("type", "online-clients");
        messageMap.put("clients", onlineClients);

        String message = mapper.writeValueAsString(messageMap);
        adminSession.sendMessage(new TextMessage(message));
    }

    // 广播在线设备列表给所有管理员
    private void broadcastOnlineClients() {
        List<Map<String, String>> onlineClients = getOnlineClients();
        String message;
        try {
            Map<String, Object> messageMap = new HashMap<>();
            messageMap.put("type", "online-clients");
            messageMap.put("clients", onlineClients);

            message = mapper.writeValueAsString(messageMap);
        } catch (Exception e) {
            e.printStackTrace();
            return;
        }

        // 遍历所有管理员会话并发送
        synchronized (adminSessions) {
            // 清理无效会话
            adminSessions.removeIf(session -> !session.isOpen());

            for (WebSocketSession session : adminSessions) {
                try {
                    if (session.isOpen()) {
                        session.sendMessage(new TextMessage(message));
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        String clientId = sessionToClientId.remove(session.getId());
        if (clientId != null) {
            clients.remove(clientId);
            clientRoles.remove(clientId);
            adminSessions.remove(session);

            // 广播更新后的在线列表
            broadcastOnlineClients();
            System.out.println("设备断开连接: " + clientId);
        }
    }

    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        System.err.println("WebSocket传输错误: " + exception.getMessage());
    }

    public List<Map<String, String>> getOnlineClients() {
        List<Map<String, String>> onlineClients = new ArrayList<>();
        for (Map.Entry<String, WebSocketSession> entry : clients.entrySet()) {
            Map<String, String> snap = new ConcurrentHashMap<>();
            String clientId = entry.getKey();
            WebSocketSession session = entry.getValue();
            if (session.isOpen() && "client".equals(clientRoles.get(clientId))) {
                snap.put(clientId, clientRoles.get(clientId));
                // 写个查询根据机构代码查询机构信息
                List<Map<String, Object>> jigou = sysUserInfoMapper.getJigou(clientId);
                if (jigou != null && jigou.size() > 0) {
                    System.out.println("jigou: " + jigou);
                    // snap.put("jigou", jigou.get(0).get("deptName").toString());
                    snap.put("year", jigou.get(0).get("year").toString());
                    snap.put("name", jigou.get(0).get("dept_name").toString());
                    snap.put("organizationcode", jigou.get(0).get("organizationcode").toString());
                    snap.put("contactPerson", jigou.get(0).get("contact_person").toString());
                    snap.put("contactTel", jigou.get(0).get("contact_tel").toString());
                    snap.put("type", "100");
                    snap.put("clientId", jigou.get(0).get("organizationcode").toString());
                }
                onlineClients.add(snap);
            }
        }
        System.out.println("在线设备列表: " + onlineClients);
        return onlineClients;
    }

    public boolean sendTo(String clientId, String payload) {
        WebSocketSession s = clients.get(clientId);
        try {
            if (s != null && s.isOpen()) {
                s.sendMessage(new TextMessage(payload));
                return true;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }
}
